package com.ssm.controller;

import com.ssm.domain.SysLog;
import com.ssm.service.ISysLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * 日志类
 */
@Component
@Aspect
public class LogAop {

    private Date visitTime; //开始时间
    private Class clazz; //访问的类
    private Method method; //访问的方法
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private ISysLogService sysLogService;

    //前置通知 主要是获取开始时间，执行的类时哪一个，执行的是哪一个方法
    @Before("execution(* com.ssm.controller.*.*(..))")
    public void doBefore(JoinPoint jp) throws NoSuchMethodException {
        visitTime = new Date(); //当时时间就是开始访问时间
        clazz = jp.getTarget().getClass(); //具体要访问的类
        String methodName = jp.getSignature().getName(); //获取访问的方法的名称
        Object[] args = jp.getArgs(); //获取访问的方法的参数

        //获取具体执行的方法的Method对象
        if(args == null || args.length == 0) {
            method = clazz.getMethod(methodName); //只能获取参数的方法
        } else {
            Class[] classArgs = new Class[args.length];
            for(int i = 0; i < args.length; i++) {
                classArgs[i] = args[i].getClass();
            }
            clazz.getMethod(methodName, classArgs);
        }
        System.out.println(visitTime + " " + clazz);
    }

    //后置通知
    @After("execution(* com.ssm.controller.*.*(..))")
    public void doAfter(JoinPoint jp) throws Exception {
        long time = new Date().getTime() - visitTime.getTime();

        String url = "";
        //获取url  需要通过反射完成操作
        if(clazz != null && method != null && clazz != LogAop.class) {
            //获取类上的@RequestMapping
            RequestMapping classAnnotation =(RequestMapping) clazz.getAnnotation(RequestMapping.class);
            if(classAnnotation!=null) {
                String[] classValue = classAnnotation.value();

                //获取方法上的value值
                RequestMapping methodAnnotation = method.getAnnotation(RequestMapping.class);
                if(methodAnnotation!=null) {
                    String[] methodValue = methodAnnotation.value();

                    url = classValue[0] + methodValue[0];
                    if (!url.equals("/sysLog/findAll.do")&&!url.equals("/sysLog/findAllsortByDate.do")&&!url.equals("/sysLog/show.do")) {
                        //获取访问的IP地址
                        String ip=request.getRemoteAddr();

                        //获取当前操作的用户
                        SecurityContext context = SecurityContextHolder.getContext(); ///从上下文中获取当前的用户
                        User user = (User) context.getAuthentication().getPrincipal();
                        String username = user.getUsername();

                        //将相关日志信息封装到SysyLog对象中
                        SysLog sysLog = new SysLog();
                        sysLog.setExecutionTime(time); //执行时长
                        sysLog.setIp(ip);
                        sysLog.setMethod("[类名] "+clazz.getName()+"[方法名] " + method.getName());
                        sysLog.setUrl(url);
                        sysLog.setUsername(username);
                        sysLog.setVisitTime(visitTime);

                        System.out.println(sysLog);
                        //调用Service完成
                        sysLogService.save(sysLog);
                    }
                }
            }
        }

    }
}
